#pragma once
#include <SimpleDef.h>
/* // 平坦模型，地址从0开始 */
#define SEGMENT_DESCRITOR_BASE  (0)
/* // 段大小限制，平坦模型，32位全1，4 GiB */
#define SEGMENT_DESCRIPTOR_LIMIT  ((0b1111 << 48) | 0xffff) 
/* // Type字段，共四位，以下字段分别对应这四位，根据需要设定 */
/* accessed */
#define SEGMENT_DESCRIPTOR_TYPE_ACCESSED  (0b1 << 40)
/* writable for data and readable for code (writable indicates readable) */
#define SEGMENT_DESCRIPTOR_TYPE_WRITE_READ  (0b1 << 41) 
/* expand-down for data or conforming for code */
#define SEGMENT_DESCRIPTOR_TYPE_EXPAND_CONFORM  (0b1 << 42) 
/* code (#11 = 1) or data (#11 = 0) */
#define SEGMENT_DESCRIPTOR_TYPE_CODE  (0b1 << 43) 
/* // code/data（S=1）或 SYSTEM（S=0）段 segment for code/data (S set) or system (S clear) */
#define SEGMENT_DESCRIPTOR_S_CODEDATA  (0b1 << 44) 
/* // 描述符特权级（只使用两种特权级，对应目态和管态）user mode, kernel mode by default */
#define SEGMENT_DESCRIPTOR_DPL_USER  (0b11 << 45) 
/* // 段是否在内存中 present (P set), not present (P clear) */
#define SEGMENT_DESCRIPTOR_PRESENT  (0b1 << 47) 
/* available bit for OS */
#define SEGMENT_DEXCRIPTION_AVAILABLE  (0b1 << 52) 
/* 64-bit code (L set), else (L clear) */
#define SEGMENT_DESCRIPTOR_LONG  (0b1 << 53) 
/* D/B Flag */
#define SEGMENT_DESCRIPTOR_DEFAULT32_BIG  (0b1 << 54) 
/* G Flag (4 KiB Granularity if set) */
#define SEGMENT_DESCRIPTOR_4KiB_GRANULARITY  (0b1 << 55)
/*
@brief 创建段描述符
@param `LIMIT` 段界限
@param `BASE` 段基址
@param `TYPE` 类型
@param `S` 系统位
@param `DPL` 描述符特权级
@param `P` 有效位
@param `AVL` 可用位
@param `DB` 默认操作数大小/栈指针大小/上边界大小控制位
@param `G` 粒度
*/
#define MAKE_SEGMENT_DESCRIPTOR(LIMIT, BASE, TYPE, S, DPL, \
    P, AVL, L, DB, G) \
( \
        ((QWORD)(LIMIT) & 0xFFFF) | /* [15:00] */ \
        (((QWORD)(BASE) & 0xFFFFFF) << 16) | /* [39:16] */\
        ((QWORD)(TYPE) << 40) | /*  [43:40] */ \
        ((QWORD)(S) << 44) |   /* [44] */ \
        ((QWORD)(DPL) << 45) | /* [46:45] */ \
        ((QWORD)(P) << 47) | /* [47] */ \
        ((QWORD)(((LIMIT) >> 16) & 0xF) << 48) | /* [51:48] */ \
        ((QWORD)(AVL) << 52) | /* [52] */ \
        ((QWORD)(L) << 53) | /* [53] */ \
        ((QWORD)(DB) << 54) | /* [54] */ \
        ((QWORD)(G) << 55) | /* [55] */ \
        (((QWORD)(BASE) >> 24) << 56) /* [63:56] */ \
)

#define RESOLVE_BASE_FROM_DESCRIPTOR(DESCRIPTOR) \
( \
    (((DESCRIPTOR) >> 32) & 0xFF000000) | \
    (((DESCRIPTOR) >> 16) & 0x00FFFFFF) \
)

/*
@brief 构造段选择子
@param `RPL` 请求特权级
@param `TI` LDT 有效位
@param `INDEX` 描述符索引
*/
#define MAKE_SEGMENT_SELECTOR(RPL, TI, INDEX) ((INDEX<< 3) | (TI << 2) | (RPL))
/* 段选择子 */
#define SELECTOR_KERNEL_CODE  MAKE_SEGMENT_SELECTOR(0, 0, 1)
#define SELECTOR_KERNEL_DATA  MAKE_SEGMENT_SELECTOR(0, 0, 2)
#define SELECTOR_USER_CODE MAKE_SEGMENT_SELECTOR(3, 0, 3)
#define SELECTOR_USER_DATA MAKE_SEGMENT_SELECTOR(3, 0, 4)
